04 - 开源产品怎么做
前置:02 篇的三条路线。
本篇回答:两个生产级开源 Agent 产品,各自把沙箱边界划在哪里、为什么划在那里。
本篇会用到的词:
| 词 | 意思 |
|---|---|
| workspace | OpenHands 的抽象:把「Agent 在哪里干活」定义成一个接口,底下可以换成本机、容器、远端服务等不同实现 |
| apptainer | 一种免 root 的容器方案,普通用户不需要管理员权限就能跑,在高性能计算集群里用得多 |
| OCI | Open Container Initiative,容器镜像与运行时的标准。符合它的运行时可以互相替换 |
| 沙箱内代理服务 | 跑在沙箱里、代表宿主执行操作的那个进程(E2B 叫 envd,OpenHands 叫 sandbox-agent-server) |
| 协议边界 | 宿主与沙箱之间只通过一组明确定义的消息通信,宿主不直接读写沙箱内部。边界越窄,缺口越少 |
一、OpenHands:把 workspace 做成可替换的抽象
OpenHands/software-agent-sdk(★1,008,MIT)的做法是不选一种沙箱,而是把"Agent 在哪里干活"抽象成 workspace,提供五种实现。
对应的源码位置与体量:
| 后端 | 路径 | 大小 |
|---|---|---|
local | openhands-sdk/openhands/sdk/workspace/local.py | 7 KB |
docker | openhands-workspace/openhands/workspace/docker/workspace.py | 15 KB |
apptainer | openhands-workspace/openhands/workspace/apptainer/workspace.py | 15.5 KB |
remote_api | openhands-workspace/openhands/workspace/remote_api/workspace.py | 16 KB |
cloud | openhands-workspace/openhands/workspace/cloud/workspace.py | 37 KB |
| 远端基类 | openhands-sdk/openhands/sdk/workspace/remote/base.py | 36 KB |
1.1 apptainer 的存在说明了什么
五个后端里最不常见的是 apptainer。它是 HPC(高性能计算)领域的容器运行时,最大特点是不需要 root 权限就能运行容器。
这个后端的存在意味着 OpenHands 认真对待一类用户:在大学或研究机构的计算集群上跑 Agent 的人。那些环境里管理员不会给你 Docker daemon 的访问权限,而 Docker 需要一个以 root 运行的守护进程。
可迁移的判断:如果你的沙箱方案强依赖 Docker daemon,就自动排除了所有共享集群场景。免 root 的容器运行时(apptainer、podman rootless)是这类环境的唯一出路。
1.2 local 后端不是遗留代码
local 意味着完全不隔离 —— Agent 直接在你的机器上执行命令。
这看起来与本专题的主题相悖,但它对应的正是 01 篇第四节说的权限路线:本地编码 Agent 要在你真实的项目目录里改文件,隔离了就没有意义。
两条路线在同一个产品里并存,由用户按场景选择。这比"我们只支持沙箱"要诚实。
1.3 cloud 后端最大不是偶然
37 KB,是 docker 后端的两倍多。多出来的部分不是隔离逻辑,而是托管服务才需要的东西:认证、配额、生命周期管理、凭证传递、状态同步。
这个体量差可以作为自建时的成本参照:隔离本身不难,难的是把它变成一个多租户服务。
二、Suna:把代理服务放进沙箱
kortix-ai/suna(★20,119)的架构选择不同。它有一个独立的应用叫 kortix-sandbox-agent-server:
| 文件 | 大小 | 职责 |
|---|---|---|
src/main.ts | 120 KB | 主服务 |
src/opencode.ts | 98 KB | 代码编辑能力 |
src/git.ts | 60 KB | git 操作 |
src/routes/web-proxy.ts | 28 KB | 沙箱内的网页代理 |
src/monitor-runner.ts | 27 KB | 运行监控 |
宿主侧则有对应的组件:
| 文件 | 大小 | 职责 |
|---|---|---|
apps/api/src/sandbox-proxy/routes/preview.ts | 83 KB | 预览流量代理 |
apps/api/src/platform/services/session-sandbox.ts | 53 KB | 会话与沙箱的绑定 |
apps/api/src/projects/sandbox-turn-lifecycle.ts | 43 KB | 按对话轮次管理沙箱生命周期 |
apps/api/src/projects/lib/sandbox-env-sync.ts | 57 KB | 环境变量同步 |
packages/shared/src/sandbox/dockerfile-layer.ts | 59 KB | 镜像分层 |